package com.tony.easymvc.core.controller;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tony.easymvc.core.DefaultProjectGenerator;
import com.tony.easymvc.core.FileGenerator;
import com.tony.easymvc.core.bean.ConfigModel;
import com.tony.easymvc.core.bean.GeneratorManifest;
import com.tony.easymvc.core.bean.ModuleConfig;
import com.tony.easymvc.po.HtmlOperation;
import com.tony.easymvc.po.OrMapping;
import com.tony.easymvc.po.ProjectBiz;
import com.tony.easymvc.po.ProjectTables;

public class ControllerGen {

    private ConfigModel config;

    public ControllerGen(ConfigModel config) {
        super();
        this.config = config;
    }

    public void generator() throws IOException {
        loadManifest();
    }

    private void loadManifest() throws IOException {
        // Set<String> modelNames = config.getMappings().keySet();

        List<ProjectBiz> bizs = config.getProject().getProjectBizs();
        List<GeneratorManifest> manifestsIndex = Lists.newArrayList();
        {
            GeneratorManifest gm1 = new GeneratorManifest();
            gm1.setFilename("index.html");
            gm1.setPath(config.getWebappPath() + "/module/index/");
            gm1.setTmplName("tmpl/server/index/moduleindex.tmpl");
            manifestsIndex.add(gm1);
            gm1 = new GeneratorManifest();
            gm1.setFilename("index.html");
            gm1.setPath(config.getWebappPath() + "/");
            gm1.setTmplName("tmpl/server/index/index.tmpl");
            manifestsIndex.add(gm1);
            gm1 = new GeneratorManifest();
            gm1.setFilename("menu.json");
            gm1.setPath(config.getWebappPath() + "/resources/assets/data/");
            gm1.setTmplName("tmpl/server/menu/menu.tmpl");
            manifestsIndex.add(gm1);
            FileGenerator fg = new FileGenerator(manifestsIndex);
            Map<String, Object> c = Maps.newHashMap();
            c.put("config", config);
            fg.generator(c);
        }
        for (ProjectBiz biz : bizs) {
            List<ProjectTables> projectTables = biz.getProjectTables();
            for (ProjectTables table : projectTables) {
                List<GeneratorManifest> manifests = Lists.newArrayList();
                String objectName = table.getObjectName();

                GeneratorManifest gm = new GeneratorManifest();
                gm.setFilename("index.js");
                gm.setPath(config.getWebappPath() + "/module/" + objectName.toLowerCase() + "/");
                gm.setTmplName("tmpl/server/module/indexjs.tmpl");
                manifests.add(gm);

                gm = new GeneratorManifest();
                gm.setFilename("index.html");
                gm.setPath(config.getWebappPath() + "/module/" + objectName.toLowerCase() + "/");
                gm.setTmplName("tmpl/server/module/index.tmpl");
                manifests.add(gm);

                gm = new GeneratorManifest();
                gm.setFilename("add_edit.html");
                gm.setPath(config.getWebappPath() + "/module/" + objectName.toLowerCase() + "/");
                gm.setTmplName("tmpl/server/module/add_edit.tmpl");
                manifests.add(gm);

                gm = new GeneratorManifest();
                gm.setFilename("add_edit.js");
                gm.setPath(config.getWebappPath() + "/module/" + objectName.toLowerCase() + "/");
                gm.setTmplName("tmpl/server/module/add_editjs.tmpl");
                manifests.add(gm);

                gm = new GeneratorManifest();
                gm.setFilename("add_edit.js");
                gm.setPath(config.getWebappPath() + "/module/" + objectName.toLowerCase() + "/");
                gm.setTmplName("tmpl/server/module/add_editjs.tmpl");
                manifests.add(gm);
                
                

                // package ${return config.project.scanPackage;}.api.${return
                // modelName;}.service;

                String apiName = config.getModules().get(ModuleConfig.API).get(0).getArtifactId();
                String packageName = config.getAnnotationPackage() + ".api." + biz.getBizName() + ".service";
                String resultPackageName = config.getAnnotationPackage() + ".api." + biz.getBizName() + ".resultBean";
                String paramPackageName = config.getAnnotationPackage() + ".api." + biz.getBizName() + ".paramBean";

                String apiPath = config.getParentProjectPath() + "/" + apiName + "/" + DefaultProjectGenerator.SRC_MAIN_JAVA + "/" + packageName.replaceAll("\\.", "/") + "/";
                String resultBeanPath = config.getParentProjectPath() + "/" + apiName + "/" + DefaultProjectGenerator.SRC_MAIN_JAVA + "/" + resultPackageName.replaceAll("\\.", "/") + "/";
                String paramBeanapiPath = config.getParentProjectPath() + "/" + apiName + "/" + DefaultProjectGenerator.SRC_MAIN_JAVA + "/" + paramPackageName.replaceAll("\\.", "/") + "/";
                // api
                gm = new GeneratorManifest();
                gm.setFilename(objectName + "Service.java");
                gm.setPath(apiPath);
                gm.setTmplName("tmpl/api/XService.tmpl");
                manifests.add(gm);
                //resultBean
                gm = new GeneratorManifest();
                gm.setFilename(objectName + "ResultBean.java");
                gm.setPath(resultBeanPath);
                gm.setTmplName("tmpl/api/XResultBean.tmpl");
                manifests.add(gm);
                //paramBean
                gm = new GeneratorManifest();
                gm.setFilename(objectName + "ParamBean.java");
                gm.setPath(paramBeanapiPath);
                gm.setTmplName("tmpl/api/XParamBean.tmpl");
                manifests.add(gm);
                
                String serverName = config.getModules().get(ModuleConfig.SERVER).get(0).getArtifactId();

//              mappingconfig.tmpl
                gm = new GeneratorManifest();
                gm.setFilename("mapping.config");
                gm.setPath(config.getParentProjectPath() + "/" + serverName + "/" + DefaultProjectGenerator.resourcesPath + "/");
                gm.setTmplName("tmpl/server/mappingconfig.tmpl");
                gm.setAppend(true);
                manifests.add(gm);

                String bizArtifactId = null;
                for (int i = 0; i < config.getModules().get(ModuleConfig.BIZ).size(); i++) {
                    if (config.getModules().get(ModuleConfig.BIZ).get(i).getBizName().equals(biz.getBizName())) {
                        bizArtifactId = config.getModules().get(ModuleConfig.BIZ).get(i).getArtifactId();
                        break;
                    }
                }

                String bizPackageName = config.getAnnotationPackage() + ".biz.service.impl";
                String bizPackagePath = config.getParentProjectPath() + "/" + bizArtifactId + "/" + DefaultProjectGenerator.SRC_MAIN_JAVA + "/" + bizPackageName.replaceAll("\\.", "/") + "/";

                // biz
                gm = new GeneratorManifest();
                gm.setFilename(objectName + "ServiceImpl.java");
                gm.setPath(bizPackagePath);
                gm.setTmplName("tmpl/biz/XServiceImpl.tmpl");
                manifests.add(gm);

                String conName = config.getModules().get(ModuleConfig.CONTROLLER).get(0).getArtifactId();
                String copackage = config.getAnnotationPackage() + ".controller";
                String copath = config.getParentProjectPath() + "/" + conName + "/" + DefaultProjectGenerator.SRC_MAIN_JAVA + "/" + copackage.replaceAll("\\.", "/") + "/";

                // con
                gm = new GeneratorManifest();
                gm.setFilename(objectName + "Controller.java");
                gm.setPath(copath);
                gm.setTmplName("tmpl/controller/XController.tmpl");
                manifests.add(gm);

                gm = new GeneratorManifest();
                gm.setFilename("BaseController.java");
                gm.setPath(copath);
                gm.setTmplName("tmpl/controller/BaseController.tmpl");
                manifests.add(gm);

                gm = new GeneratorManifest();
                gm.setFilename("DatatableRequest.java");
                gm.setPath(copath + "bean/");
                gm.setTmplName("tmpl/controller/DatatableRequest.tmpl");
                manifests.add(gm);

                List<OrMapping> omps = biz.getMapping().get(objectName);
                if (omps == null) {
                    System.out.println("aa");
                    omps = Lists.newArrayList();
                }
                List<HtmlOperation> hops = fillHtmlOperation(omps, table);

                FileGenerator fg = new FileGenerator(manifests);
                Map<String, Object> c = Maps.newHashMap();
                c.put("config", config);
                c.put("modelName", objectName.toLowerCase());
                c.put("objectName", objectName);
                c.put("xobjectName", (objectName.charAt(0) + "").toLowerCase() + objectName.substring(1));
                c.put("biz", biz);
                c.put("htmlOperation", hops);
                c.put("projectTable", table);
                c.put("pk", table.getPrimaryKey());
                fg.generator(c, false);
            }

        }

        // {
        // List<GeneratorManifest> manifests = Lists.newArrayList();
        // GeneratorManifest gm = new GeneratorManifest();
        // gm.setFilename("BaseController.java");
        // gm.setPath(config.getControllerPath());
        // gm.setTmplName("tmpl/controller/BaseController.tmpl");
        // manifests.add(gm);
        //
        // gm = new GeneratorManifest();
        // gm.setFilename("DateTimeConverter.java");
        // gm.setPath(config.getControllerPath());
        // gm.setTmplName("tmpl/controller/DateTimeConverter.tmp");
        // manifests.add(gm);
        //
        // gm = new GeneratorManifest();
        // gm.setFilename("JsonDateValueProcessor.java");
        // gm.setPath(config.getControllerPath());
        // gm.setTmplName("tmpl/controller/JsonDateValueProcessor.tmpl");
        // manifests.add(gm);
        //
        // FileGenerator fg = new FileGenerator(manifests);
        // Map<String, Object> c = Maps.newHashMap();
        // c.put("config", config);
        // fg.generator(c);
        // }

        // for (Iterator<String> iterator = modelNames.iterator(); iterator.hasNext();)
        // {
        // List<GeneratorManifest> manifests = Lists.newArrayList();
        // String modelName = iterator.next();
        // GeneratorManifest gm = new GeneratorManifest();
        // gm.setFilename(createController(modelName));
        // gm.setPath(config.getControllerPath());
        // gm.setTmplName("tmpl/controller/XController.tmpl");
        // manifests.add(gm);
        //
        // OrMapping omp = getPrimaryKey(modelName);
        // String pkJava = omp.getJavaField();
        // FileGenerator fg = new FileGenerator(manifests);
        // Map<String, Object> c = Maps.newHashMap();
        // c.put("config", config);
        // c.put("modelName", modelName);
        // c.put("xmodelName", (modelName.charAt(0) + "").toLowerCase() +
        // modelName.substring(1));
        // c.put("xprimaryKey", (pkJava.charAt(0) + "").toUpperCase() +
        // pkJava.substring(1));
        //
        // fg.generator(c);
        // }
        //
        // for (Iterator<String> iterator = modelNames.iterator(); iterator.hasNext();)
        // {
        // List<GeneratorManifest> manifests = Lists.newArrayList();
        // String modelName = iterator.next();
        // GeneratorManifest gm = new GeneratorManifest();
        // gm.setFilename(createBizService(modelName));
        // gm.setPath(config.getBizServicePath());
        // gm.setTmplName("tmpl/biz/XService.tmpl");
        // manifests.add(gm);
        //
        // FileGenerator fg = new FileGenerator(manifests);
        // Map<String, Object> c = Maps.newHashMap();
        // c.put("config", config);
        // c.put("modelName", modelName);
        // c.put("xmodelName", (modelName.charAt(0) + "").toLowerCase() +
        // modelName.substring(1));
        // fg.generator(c);
        // }
        //
        // for (Iterator<String> iterator = modelNames.iterator(); iterator.hasNext();)
        // {
        // List<GeneratorManifest> manifests = Lists.newArrayList();
        // String modelName = iterator.next();
        // GeneratorManifest gm = new GeneratorManifest();
        // gm.setFilename(createBizServiceImpl(modelName));
        // gm.setPath(config.getBizServiceImplPath());
        // gm.setTmplName("tmpl/biz/XServiceImpl.tmpl");
        // manifests.add(gm);
        //
        // FileGenerator fg = new FileGenerator(manifests);
        // Map<String, Object> c = Maps.newHashMap();
        // c.put("config", config);
        // c.put("modelName", modelName);
        // c.put("xmodelName", (modelName.charAt(0) + "").toLowerCase() +
        // modelName.substring(1));
        // fg.generator(c);
        // }
        //
        // for (Iterator<String> iterator = modelNames.iterator(); iterator.hasNext();)
        // {
        // List<GeneratorManifest> manifests = Lists.newArrayList();
        // String modelName = iterator.next();
        // GeneratorManifest gm = new GeneratorManifest();
        // gm.setFilename(createHtml(modelName));
        // gm.setPath(config.getWebappPath() + "/module/" + modelName);
        // gm.setTmplName("tmpl/server/html/xmodule.tmpl");
        // manifests.add(gm);
        //
        // FileGenerator fg = new FileGenerator(manifests);
        // Map<String, Object> c = Maps.newHashMap();
        // c.put("config", config);
        // c.put("modelName", modelName);
        // fg.generator(c);
        // }
        //
        // for (Iterator<String> iterator = modelNames.iterator(); iterator.hasNext();)
        // {
        // List<GeneratorManifest> manifests = Lists.newArrayList();
        // String modelName = iterator.next();
        // GeneratorManifest gm = new GeneratorManifest();
        // gm.setFilename(createJs(modelName));
        // gm.setPath(config.getWebappPath() + "/module/" + modelName + "/js/");
        // gm.setTmplName("tmpl/server/html/xmodulejs.tmpl");
        // manifests.add(gm);
        // List<OrMapping> omps = config.getMappings().get(modelName);
        // ProjectTables pt = getProjectTable(modelName);
        // if (pt == null)
        // continue;
        // pt.setObjectName(modelName);
        //
        // List<HtmlOperation> hops = fillHtmlOperation(omps, pt);
        //
        // FileGenerator fg = new FileGenerator(manifests);
        // Map<String, Object> c = Maps.newHashMap();
        // c.put("config", config);
        // c.put("modelName", modelName);
        // c.put("htmlOperation", hops);
        // c.put("projectTable", pt);
        // fg.generator(c);
        // }
        // {
        // List<GeneratorManifest> manifests = Lists.newArrayList();
        // GeneratorManifest gm = new GeneratorManifest();
        // gm.setFilename("m.json");
        // gm.setPath(config.getWebappPath() + "/app/data/");
        // gm.setTmplName("tmpl/server/html/m.tmpl");
        // manifests.add(gm);
        //
        //// FileGenerator fg = new FileGenerator(manifests);
        //// List<ProjectTables> pts =
        // config.getProject().getProjectContext().getProjectTables();
        //// Map<String, Object> c = Maps.newHashMap();
        //// c.put("config", config);
        //// c.put("projectTable", pts);
        //// fg.generator(c);
        // }

    }

    private List<HtmlOperation> fillHtmlOperation(List<OrMapping> omps, ProjectTables pt) {
        List<HtmlOperation> hops = pt.getHtmlOperations();
        for (int i = 0; i < hops.size(); i++) {
            String columnName = hops.get(i).getColumnName();

            OrMapping mapping = findMapping(omps, columnName);
            if (mapping == null)
                continue;
            hops.get(i).setFieldName(mapping.getJavaField());
            // hops.get(i).setFieldType(mapping.getJdbcType());
        }
        return hops;
    }

    private OrMapping findMapping(List<OrMapping> omps, String columnName) {
        for (int j = 0; j < omps.size(); j++) {
            if (omps.get(j).getDbField().equals(columnName)) {
                return omps.get(j);
            }
        }
        return null;
    }

    private OrMapping getPrimaryKey(String modelName) {
        List<OrMapping> omps = config.getMappings().get(modelName);
        for (int i = 0; i < omps.size(); i++) {
            if (omps.get(i).isPrimaryKey()) {
                return omps.get(i);
            }
        }
        return null;
    }

    private String createHtml(String modelName) {
        return modelName + ".html";
    }

    private String createController(String modelName) {
        return modelName + "Controller.java";
    }

    private String createBizService(String modelName) {
        return modelName + "Service.java";
    }

    private String createBizServiceImpl(String modelName) {
        return modelName + "ServiceImpl.java";
    }

}
